package server;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

public class WebAppClassLoader extends ClassLoader {
    //war 包中存放class文件路径
    private String classPath;

    public WebAppClassLoader(String name, ClassLoader parent, String classPath) {
        super(name, parent);
        this.classPath = classPath;
    }

    public WebAppClassLoader(ClassLoader parent, String classPath) {
        super(parent);
        this.classPath = classPath;
    }

    public WebAppClassLoader(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        File file = getFile(name);
        try {
            byte[] bytes = getClass(file);
            Class<?> clazz = defineClass(name, bytes, 0, bytes.length);
            return clazz;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }

    private byte[] getClass(File file) throws IOException {
        try(FileInputStream fileInputStream = new FileInputStream(file)){
            FileChannel fileChannel = fileInputStream.getChannel();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            WritableByteChannel writableByteChannel = Channels.newChannel(byteArrayOutputStream);
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            while (true){
                int read = fileChannel.read(byteBuffer);
                if(read == 0 || read == -1){
                    break;
                }
                byteBuffer.flip();
                writableByteChannel.write(byteBuffer);
                byteBuffer.clear();
            }

            return byteArrayOutputStream.toByteArray();
        }
    }

    private File getFile(String name) {
        if(null == name || "".equals(name)){
            return null;
        }
        String classFullPath = classPath +"/"+name.replaceAll("\\.","/")+".class";
        return new File(classFullPath);
    }
}
